﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using Common.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OutDbContext;
using Senparc.Weixin;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.OAuth;
using User.Api.Helpers;

namespace User.Api.Controllers
{
    public class AuthController : ApiController
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(AuthController));
        private static readonly string WxOauth2State = "GbkYin666";

        static Dictionary<string, OAuthAccessTokenResult> OAuthCodeCollection = new Dictionary<string, OAuthAccessTokenResult>();
        static object OAuthCodeCollectionLock = new object();

        [AllowAnonymous]
        [HttpGet]
        [ActionName("WxOauth2")]
        public HttpResponseMessage WxOauth2(string url, string code, string state)
        {
            string failedUrl = ConfigurationManager.AppSettings["H5BaseAddress"] + "/index/401";

            var appId = ConfigurationManager.AppSettings["WeixinAppId"];
            var secret = ConfigurationManager.AppSettings["WeixinAppSecret"];

            if (string.IsNullOrEmpty(code))
            {
                var res = Request.CreateResponse(HttpStatusCode.Redirect);
                res.Headers.Location = new Uri(failedUrl);
                return res;
            }

            if (state != WxOauth2State)
            {
                var res = Request.CreateResponse(HttpStatusCode.Redirect);
                res.Headers.Location = new Uri(failedUrl);
                return res;
            }

            //OAuthAccessTokenResult result = null;

            ////通过，用code换取access_token
            //try
            //{
            //    result = OAuthApi.GetAccessToken(appId, secret, code);
            //}
            //catch (Exception ex)
            //{
            //    Logger.ErrorFormat("微信网页授权获取用户信息第一步出错，授权码:{0},信息：{1}", code, JsonConvert.SerializeObject(ex));

            //    var res = Request.CreateResponse(HttpStatusCode.Redirect);
            //    res.Headers.Location = new Uri(failedUrl);
            //    return res;
            //}
            //if (result.errcode != ReturnCode.请求成功)
            //{
            //    var res = Request.CreateResponse(HttpStatusCode.Redirect);
            //    res.Headers.Location = new Uri(failedUrl);
            //    return res;
            //}

            //OAuthUserInfo userInfo = null;
            //try
            //{
            //    userInfo = OAuthApi.GetUserInfo(result.access_token, result.openid);
            //    // TODO 获取用户信息
            //}
            //catch (ErrorJsonResultException ex)
            //{
            //    Logger.ErrorFormat("微信网页授权获取用户信息第二步出错，信息：{0}", JsonConvert.SerializeObject(ex));
            //}

            //string openId;
            OAuthAccessTokenResult result = null;

            try
            {
                //通过，用code换取access_token

                var isSecondRequest = false;
                lock (OAuthCodeCollectionLock)
                {
                    isSecondRequest = OAuthCodeCollection.ContainsKey(code);
                }

                if (!isSecondRequest)
                {
                    //第一次请求
                    //LogUtility.Weixin.DebugFormat("第一次微信OAuth到达，code：{0}", code);
                    lock (OAuthCodeCollectionLock)
                    {
                        OAuthCodeCollection[code] = null;
                    }
                }
                else
                {
                    //第二次请求
                    //LogUtility.Weixin.DebugFormat("第二次微信OAuth到达，code：{0}", code);

                    lock (OAuthCodeCollectionLock)
                    {
                        result = OAuthCodeCollection[code];
                    }
                }

                try
                {
                    try
                    {
                        result = result ?? OAuthApi.GetAccessToken(appId, secret, code);
                    }
                    catch (Exception ex)
                    {
                        //return Content("OAuth AccessToken错误：" + ex.Message);
                        Logger.ErrorFormat("微信网页授权获取用户信息第一步出错，授权码:{0},信息：{1}", code, JsonConvert.SerializeObject(ex));
                        var res = Request.CreateResponse(HttpStatusCode.Redirect);
                        res.Headers.Location = new Uri(failedUrl);
                        return res;
                    }

                    if (result != null)
                    {
                        lock (OAuthCodeCollectionLock)
                        {
                            OAuthCodeCollection[code] = result;
                        }
                    }
                }
                catch (ErrorJsonResultException ex)
                {
                    if (ex.JsonResult.errcode == ReturnCode.不合法的oauth_code)
                    {
                        //code已经被使用过
                        lock (OAuthCodeCollectionLock)
                        {
                            result = OAuthCodeCollection[code];
                        }
                    }
                }

                //openId = result != null ? result.openid : null;
            }
            catch (Exception ex)
            {
                //return Content("授权过程发生错误：" + ex.Message);
                Logger.ErrorFormat("微信网页授权授权过程发生错误:{0},信息：{1}", ex.Message);
                var res = Request.CreateResponse(HttpStatusCode.Redirect);
                res.Headers.Location = new Uri(failedUrl);
                return res;
            }

            if (result == null)
            {
                var res = Request.CreateResponse(HttpStatusCode.Redirect);
                res.Headers.Location = new Uri(failedUrl);
                return res;
            }

            long userId = 0;
            var openId = result.openid;

            var isNewUser = false;
            using (var ctx = new FsssdqfybjyEntities())
            {
                var user = ctx.WxUsers.FirstOrDefault(x => x.OpenId == openId);
                if (user != null)
                {
                    if (user.UnsubscribeDt != null)
                    {
                        isNewUser = true;
                    }
                    user.RecStatus = 1;
                    user.LastActiveDt = DateTime.Now;
                    user.RecUpdateDt = DateTime.Now;

                    //user.RecStatus = 1;
                    //user.LastActiveDt = DateTime.Now;
                    //user.UnsubscribeDt = null;
                    //user.RecUpdateDt = DateTime.Now;
                }
                else
                {
                    isNewUser = true;
                    user = new OutDbContext.WxUser
                    {
                        OpenId = openId,
                        SubscribeDt = DateTime.Now,
                        LastActiveDt = DateTime.Now,
                        //IsBitcareMember = false,
                        RecStatus = 1,
                        RecCreateDt = DateTime.Now
                    };

                    ctx.WxUsers.Add(user);
                }

                ctx.SaveChanges();
                userId = user.Id;
            }

            if (isNewUser && url.IndexOf("thirdPartyName", StringComparison.Ordinal) >= 0)
            {
                var h5BaseAddress = ConfigurationManager.AppSettings["H5BaseAddress"];
                url = h5BaseAddress + "/index/subscribe-wx";
            }

            var response = Request.CreateResponse(HttpStatusCode.Redirect);
            response.Headers.Location = new Uri(url);

            var cookie = new CookieHeaderValue("AzuCookie",
                LocalUserTokenHelper.GenerateLocalToken(userId, openId));
            //cookie.Domain = Request.RequestUri.Host;
            cookie.Path = "/";
            response.Headers.AddCookies(new[] { cookie });

            return response;
        }

        [HttpGet]
        [AllowAnonymous]
        [ActionName("GetWxOauth2Url")]
        public string GetWxOauth2Url(string url)
        {
            var baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
            var appId = ConfigurationManager.AppSettings["WeixinAppId"];

            var oauth2Url = OAuthApi.GetAuthorizeUrl(appId,
                baseAddress
                + "api/Auth/WxOauth2?url="
                + HttpUtility.UrlEncode(url), WxOauth2State, OAuthScope.snsapi_userinfo);

            return oauth2Url;
        }

        /// <summary>
        /// 获取oauth2的网页地址
        /// </summary>
        /// <param name="request">比如  {routePath:"/index/portal"} </param>
        /// <returns></returns>
        [HttpPost]
        [AllowAnonymous]
        [ActionName("GetH5Url")]
        public string GetH5Url(JObject request)
        {
            var routePath = request["routePath"].ToString();
            var h5BaseAddress = ConfigurationManager.AppSettings["H5BaseAddress"];
            var baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
            var appId = ConfigurationManager.AppSettings["WeixinAppId"];

            var url = h5BaseAddress + routePath;

            var oauth2Url = OAuthApi.GetAuthorizeUrl(appId,
                baseAddress
                + "api/Auth/WxOauth2?url="
                + HttpUtility.UrlEncode(url), WxOauth2State, OAuthScope.snsapi_userinfo);

            return oauth2Url;
        }
    }
}
